package com.icw.basis;

import java.util.IdentityHashMap;
import java.util.LinkedHashMap;
import java.util.Map;

import com.icw.utility.PoEntityHelper;

public class DiyMap<K, V> {

	private final IdentityHashMap<Object, V> cache = new IdentityHashMap<>();

	private final Map<Object, V> entityCache = new LinkedHashMap<>();

	public void put(K key, V value) {
		mapAndKey(key, (map, k) -> map.put(k, value));
	};

	public V get(Object key) {
		return mapAndKey(key, (map, k) -> map.get(k));
	};

	public boolean contains(Object key) {
		return mapAndKey(key, (map, k) -> map.containsKey(k));
	};

	private String getEntityKey(Object o) {
		Class<?> entityClass = o.getClass();
		while (entityClass.getSuperclass() != BasePoEntity.class) {
			entityClass = entityClass.getSuperclass();
		}
		return entityClass.getName() + "[" + PoEntityHelper.readValueByProperty(o, "id") + "]";
	}

	private boolean isEntityWithId(Object o) {
		return BasePoEntity.class.isInstance(o) && PoEntityHelper.readValueByProperty(o, "id") != null;
	}

	private static interface MK<V, R> {

		R exec(Map<Object, V> map, Object k);
	}

	private <R> R mapAndKey(Object k, MK<V, R> mk) {
		if (isEntityWithId(k)) {
			return mk.exec(entityCache, getEntityKey(k));
		} else {
			return mk.exec(cache, k);
		}
	}
}